home *** CD-ROM | disk | FTP | other *** search
- // midicat v1.0 written by Günter Nagler 1996 (gnagler@ihm.tu-graz.ac.at)
- // concatenate midi format 0 files
- #include "midiio.hpp"
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
-
- char* input = 0;
- char* output = 0;
-
- #define MAXSONGS 50
-
- int songnr = 0;
- unsigned long lasttime[MAXSONGS];
- int resolution = 0;
-
- MidiWrite* write = 0;
-
- class MidiCat : public MidiRead
- {
- public:
- MidiCat(char* name);
-
- virtual void head(unsigned version, unsigned tracks, unsigned unitsperbeat);
- virtual void track(int trackno, long length, int channel);
- virtual void endtrack(int trackno);
-
- virtual void text(int what, int len, char* whattext, unsigned char* txt);
- virtual void meta(int what, int len, unsigned char* data);
- virtual void end();
- virtual void tact(int nom, int denom, int v1, int v2);
- virtual void tempo(unsigned long ticks);
- virtual void program(int prg, int channel);
- virtual void control(int channel, int what, int value);
- virtual void highbank(int channel, int val);
- virtual void wheel(int channel, int val);
- virtual void breath(int channel, int val);
- virtual void foot(int channel, int val);
- virtual void portamentotime(int channel, int val);
- virtual void data(int channel, int val);
- virtual void volume(int channel, int val);
- virtual void balance(int channel, int val);
- virtual void expression(int channel, int val);
- virtual void lowbank(int channel, int val);
- virtual void hold(int channel, int val);
- virtual void reverb(int channel, int val);
- virtual void chorus(int channel, int val);
- virtual void datainc(int channel, int val);
- virtual void datadec(int channel, int val);
- virtual void noteon(int channel, int note, int vel);
- virtual void noteoff(int channel, int note, int vel);
- virtual void time(unsigned long ticks);
- virtual void pitchbend(int channel, int val);
- virtual void polyaftertouch(int channel, int note, int val);
- virtual void aftertouch(int channel, int val);
- virtual void songpos(unsigned pos);
- virtual void songselect(unsigned char song);
- virtual void tunerequest();
- virtual void timingclock();
- virtual void start();
- virtual void cont();
- virtual void stop();
- virtual void activesense();
- virtual void sysex(int syslen, unsigned char* sysdata);
- virtual void error(const char* msg);
- virtual void warning(const char* msg);
-
- virtual void percent(int perc);
- };
-
- MidiCat::MidiCat(char* name) : MidiRead(name)
- {
- }
-
- void MidiCat::head(unsigned version, unsigned tracks, unsigned unitsperbeat)
- {
- if (!write)
- {
- printf("%s: format %d, %d tracks, resolution %d\n", midiname_, version, tracks, unitsperbeat);
- if (!resolution)
- resolution = unitsperbeat;
- else if (resolution != unitsperbeat)
- // common multiplyer of resolution and unitsperbeat
- {
- int divider = 1;
-
- for (int d = 2; d <= resolution && d <= unitsperbeat; d++)
- if (resolution % d == 0 && unitsperbeat % d == 0)
- divider = d;
- // greatest common divider
- if (divider == 1)
- {
- if (unitsperbeat > divider)
- resolution = unitsperbeat;
- }
- else
- resolution *= unitsperbeat / divider;
- }
- }
- }
-
- void MidiCat::track(int trackno, long length, int channel)
- {
- }
-
- void MidiCat::endtrack(int trackno)
- {
- }
-
- void MidiCat::text(int what, int len, char* whattext, unsigned char* txt)
- {
- if (write && getcurunit() <= lasttime[songnr])
- write->text(what, len, txt);
- }
-
- void MidiCat::meta(int what, int len, unsigned char* data)
- {
- if (write && getcurunit() <= lasttime[songnr])
- write->meta(what, len, data);
- }
-
- void MidiCat::end()
- {
- if (write)
- {
- write->cleardelta();
- write->time(resolution); // 1 tact pause!
- }
- }
-
- void MidiCat::tact(int nom, int denom, int v1, int v2)
- {
- if (write && getcurunit() <= lasttime[songnr])
- write->tact(nom, denom, v1, v2);
- }
-
- void MidiCat::tempo(unsigned long ticks)
- {
- if (write && getcurunit() <= lasttime[songnr])
- write->tempo(ticks);
- }
-
- void MidiCat::time(unsigned long ticks)
- {
- if (write && getcurunit() <= lasttime[songnr])
- {
- if (unitsperbeat_ != resolution)
- {
- ticks = (int)(((long)resolution * (long)ticks) / (long)unitsperbeat_);
- }
- write->time(ticks);
- }
- }
-
- void MidiCat::program(int channel, int prg)
- {
- if (write && getcurunit() <= lasttime[songnr])
- write->program(channel, prg);
- }
-
- void MidiCat::control(int channel, int what, int value)
- {
- if (write && getcurunit() <= lasttime[songnr])
- write->control(channel, what, value);
- }
-
- void MidiCat::balance(int channel, int val)
- {
- if (write && getcurunit() <= lasttime[songnr])
- write->balance(channel, val);
- }
-
- void MidiCat::highbank(int channel, int val)
- {
- if (write && getcurunit() <= lasttime[songnr])
- write->highbank(channel, val);
- }
-
- void MidiCat::wheel(int channel, int val)
- {
- if (write && getcurunit() <= lasttime[songnr])
- write->wheel(channel, val);
- }
-
- void MidiCat::breath(int channel, int val)
- {
- if (write && getcurunit() <= lasttime[songnr])
- write->breath(channel, val);
- }
-
- void MidiCat::foot(int channel, int val)
- {
- if (write && getcurunit() <= lasttime[songnr])
- write->foot(channel, val);
- }
-
- void MidiCat::portamentotime(int channel, int val)
- {
- if (write && getcurunit() <= lasttime[songnr])
- write->portamentotime(channel, val);
- }
-
- void MidiCat::data(int channel, int val)
- {
- if (write && getcurunit() <= lasttime[songnr])
- write->data(channel, val);
- }
-
- void MidiCat::volume(int channel, int val)
- {
- if (write && getcurunit() <= lasttime[songnr])
- write->volume(channel, val);
- }
-
- void MidiCat::expression(int channel, int val)
- {
- if (write && getcurunit() <= lasttime[songnr])
- write->expression(channel, val);
- }
-
- void MidiCat::lowbank(int channel, int val)
- {
- if (write && getcurunit() <= lasttime[songnr])
- write->lowbank(channel, val);
- }
-
- void MidiCat::hold(int channel, int val)
- {
- if (write && getcurunit() <= lasttime[songnr])
- write->hold(channel, val);
- }
-
- void MidiCat::reverb(int channel, int val)
- {
- if (write && getcurunit() <= lasttime[songnr])
- write->reverb(channel, val);
- }
-
- void MidiCat::chorus(int channel, int val)
- {
- if (write && getcurunit() <= lasttime[songnr])
- write->chorus(channel, val);
- }
-
- void MidiCat::datainc(int channel, int val)
- {
- if (write && getcurunit() <= lasttime[songnr])
- write->datainc(channel, val);
- }
-
- void MidiCat::datadec(int channel, int val)
- {
- if (write && getcurunit() <= lasttime[songnr])
- write->datadec(channel, val);
- }
-
- void MidiCat::noteon(int channel, int note, int vel)
- {
- if (write)
- {
- if(getcurunit() <= lasttime[songnr])
- write->noteon(channel, note, vel);
- }
- else
- lasttime[songnr] = getcurunit();
- }
-
- void MidiCat::noteoff(int channel, int note, int vel)
- {
- if (write)
- {
- if(getcurunit() <= lasttime[songnr])
- write->noteoff(channel, note, vel);
- }
- else
- lasttime[songnr] = getcurunit();
- }
-
- void MidiCat::pitchbend(int channel, int val)
- {
- if (write)
- {
- if(getcurunit() <= lasttime[songnr])
- write->pitchbend(channel, val);
- }
- else
- lasttime[songnr] = getcurunit();
- }
-
- void MidiCat::polyaftertouch(int channel, int note, int val)
- {
- if (write)
- {
- if(getcurunit() <= lasttime[songnr])
- write->polyaftertouch(channel, note, val);
- }
- else
- lasttime[songnr] = getcurunit();
- }
-
- void MidiCat::aftertouch(int channel, int val)
- {
- if (write)
- {
- if(getcurunit() <= lasttime[songnr])
- write->aftertouch(channel, val);
- }
- else
- lasttime[songnr] = getcurunit();
- }
-
- void MidiCat::songpos(unsigned pos)
- {
- if (write && getcurunit() <= lasttime[songnr])
- write->songpos(pos);
- }
-
- void MidiCat::songselect(unsigned char song)
- {
- if (write && getcurunit() <= lasttime[songnr])
- write->songselect(song);
- }
-
- void MidiCat::tunerequest()
- {
- if (write && getcurunit() <= lasttime[songnr])
- write->tunerequest();
- }
-
- void MidiCat::timingclock()
- {
- if (write && getcurunit() <= lasttime[songnr])
- write->timingclock();
- }
-
- void MidiCat::start()
- {
- if (write && getcurunit() <= lasttime[songnr])
- write->start();
- }
-
- void MidiCat::cont()
- {
- if (write && getcurunit() <= lasttime[songnr])
- write->cont();
- }
-
- void MidiCat::stop()
- {
- if (write && getcurunit() <= lasttime[songnr])
- write->stop();
- }
-
- void MidiCat::activesense()
- {
- if (write && getcurunit() <= lasttime[songnr])
- write->activesense();
- }
-
- void MidiCat::sysex(int syslen, unsigned char* sysdata)
- {
- if (write && getcurunit() <= lasttime[songnr])
- write->sysex(syslen, sysdata);
- }
-
- void MidiCat::percent(int perc)
- {
- fprintf(stderr, "%-3d%%\r", perc);
- }
-
- void MidiCat::error(const char* msg)
- {
- printf("Error: %s\n", msg);
- exit(1);
- }
-
- void MidiCat::warning(const char* msg)
- {
- printf("Warning: %s\n", msg);
- }
-
- int scanmidi(char* input)
- {
- lasttime[songnr] = 0; // find end of
-
- MidiCat midi(input);
- if (!midi.getf())
- {
- perror(input);
- return 1;
- }
- midi.options_ = OPTION_NOMETAEVENTS | OPTION_NOSYSEVENTS | OPTION_NOCONTROLS;
- if (!midi.run())
- {
- fprintf(stderr, "%s is not a correct midi\n", input);
- return 1;
- }
- if (midi.version_ != 0)
- {
- fprintf(stderr, "%s is format %d midi!\nConvert it to format 0 using midi%dto0\n",
- input, midi.version_, midi.version_);
- return 1;
- }
- return 0;
- }
-
- void usage()
- {
- fprintf(stderr, "MidiCat concatenates midi format 0 files to play sequentially\n");
- fprintf(stderr, "usage: MidiCat file1.mid file2.mid ... result.mid\n");
- exit(1);
- }
-
- int main(int argc, char**argv)
- {
- argc--; argv++;
- while (argc > 0 && **argv == '-')
- {
- fprintf(stderr, "invalid option %s\n", *argv);
- argc--; argv++;
- usage();
- }
- if (argc < 2)
- usage();
-
- output = argv[argc - 1];
- argc--;
- for (songnr = 0; songnr < argc; songnr++)
- if (strcmp(argv[songnr], output) == 0)
- {
- fprintf(stderr, "cannot convert midi to one of the input files\n");
- return 1;
- }
- FILE* testf = fopen(output, "r");
- if (testf)
- {
- fclose(testf);
- fprintf(stderr, "output file %s already existing. aborting...\n", output);
- return 1;
- }
-
- // test if all input files are available
- for (songnr = 0; songnr < argc; songnr++)
- {
- if (scanmidi(input=argv[songnr]))
- return 1;
- }
- write = new MidiWrite(output);
- if (!write)
- {
- fprintf(stderr, "out of memory\n");
- return 1;
- }
- if (!write->getf())
- {
- perror(output);
- return 1;
- }
- write->head(0, 1, resolution);
- write->track();
-
- for (songnr = 0; songnr < argc; songnr++)
- {
- static char* seperator = "-- midi file added by midicat --";
-
- write->text(meta_marker, strlen(seperator), seperator);
- // initialize new midi parameters
- write->tact(4, 4, 24, 8);
- write->tempo(tempo_120bpm);
- for (int ch = 0; ch < 16; ch++)
- {
- if (ch != gm_drumchannel)
- write->program(ch, 0); // piano
- write->volume(ch, volume_full);
- write->balance(ch, balance_center);
- write->reverb(ch, 13);
- write->chorus(ch, 13);
- }
-
- MidiCat midi(input = argv[songnr]);
- if (!midi.getf())
- {
- perror(input);
- return 1;
- }
- midi.options_ = OPTION_NOCONTROLS|OPTION_NOSYSEVENTS;
- if (!midi.run())
- fprintf(stderr, "%s: midi read error at %04lX\n", input, midi.getpos());
- }
- write->end();
-
- delete write; write = 0;
- printf("output written to %s:\n", output);
- songnr = 0;
- scanmidi(output);
- return 0;
- }
-